package com.zilue.payment.gateway.manage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.zilue.payment.gateway.domain.CorpDO;
import com.zilue.payment.gateway.method.BaseMethod;
import com.zilue.payment.gateway.paramter.BaseParameter;
import com.zilue.payment.gateway.paramter.ParameterCheckResult;
import com.zilue.payment.gateway.paramter.PublicParameter;
import com.zilue.payment.gateway.reurndata.PublicReturn;
import com.zilue.payment.gateway.reurndata.enums.BusinessStatusEnum;
import com.zilue.payment.gateway.reurndata.enums.RequestStatusEnum;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.stereotype.Service;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ZD on 2017/5/26.
 */
@Service
public class GatewayManager extends BaseManager {
    private Logger logger = Logger.getLogger(GatewayManager.class);

    public static Map<String, BaseMethod> beanMap = new HashMap<>();

    /**
     * 业务处理调用核心方法
     * （在这里进行业务参数校验）
     *
     * @param publicParameter
     * @return
     */
    public PublicReturn proccess(PublicParameter publicParameter) {
        //1.业务参数非空校验
        PublicReturn publicReturn = PublicReturn.createSuccessReturn(RequestStatusEnum.RequestSuccess);
        JSONObject biz_content = publicParameter.getBiz_content();
        if (biz_content == null || biz_content.isEmpty()) {
            publicReturn.setBusinessStatus(BusinessStatusEnum.ParameterIllegal);
            return publicReturn;
        }
        //2.业务参数检查
        BaseMethod bean = beanMap.get(publicParameter.getMethod());
        BaseParameter baseParameter = (BaseParameter) JSON.toJavaObject(publicParameter.getBiz_content(), bean.paramterClass());
        ParameterCheckResult checkResult = baseParameter.ParameterCheck();
        if (!checkResult.isStatus()) {
            publicReturn.setBusinessStatus(BusinessStatusEnum.ParameterIllegal);
            publicReturn.setMsg(checkResult.getDescription());
            return publicReturn;
        }
        //3.获取APPID机构
        CorpDO corpDO = queryCorpByAppid(publicParameter.getAppid());
        //7.执行目标接口方法,并返回
        try {
            return bean.doMethod(corpDO, baseParameter);
        } catch (Exception e) {
            logger.error("统一支付网关异常", e);
            if (e instanceof JSONException) {
                //参数类型转换异常
                publicReturn.setBusinessStatus(BusinessStatusEnum.ParameterIllegal);
                publicReturn.appendMsg(e.getMessage());
                return publicReturn;
            } else {
                //非已知异常
                publicReturn.setBusinessStatus(BusinessStatusEnum.Busyness);
                return publicReturn;
            }
        }
    }

    /**
     * 获取目标接口方法实例
     *
     * @param methodName
     * @param request
     * @return
     */
    public BaseMethod getBean(String methodName, HttpServletRequest request) {
        try {
            BaseMethod bean = beanMap.get(methodName);
            if (bean == null) {
                Object methodBean = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext()).getBean(methodName);
                if (methodBean != null && methodBean instanceof BaseMethod) {
                    bean = (BaseMethod) methodBean;
                    beanMap.put(methodName, bean);
                }
            }
            return bean;
        } catch (NoSuchBeanDefinitionException e) {
            return null;
        }
    }

    /**
     * 手动解析参数
     * （由于业务参数无需摘要算法，必须保证用户传递顺序不被破坏，fastjson不保证顺序）
     *
     * @param request
     * @return
     */
    public PublicParameter getPublicParamter(HttpServletRequest request) {
        try {
            int length = request.getContentLength();
            if (length == 0)
                return new PublicParameter();
            byte[] bytes = new byte[length];
            ServletInputStream inputStream = request.getInputStream();
            inputStream.read(bytes);
            inputStream.close();
            String content = new String(bytes, "utf-8");

            JSONObject jsonObject = JSONObject.parseObject(content);
            PublicParameter publicParamter = JSON.toJavaObject(jsonObject, PublicParameter.class);
            JsonObject object = (JsonObject) new JsonParser().parse(content);//gson可以保证顺序
            JsonObject biz_content = object.getAsJsonObject("biz_content");
            if (biz_content != null) {
                String bizContent = biz_content.toString();
                publicParamter.setBizContent(bizContent);
            }
            return publicParamter;
        } catch (IOException e) {
            return null;
        }

    }

}
